using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using ThirdPartyNinjas.XnaUtility;
using LuaInterface;
using ElementumForever.Utility;
using System;
using ElementumForever.Factory;
using ElementumForever.Editer;
using ElementumForever.Interfaces;
using ElementumForever.Entity.Scene;

namespace ElementumForever
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class MainGame : Game
    {
        static GraphicsDeviceManager graphics;
        public SpriteBatch SpriteBatch { get; private set; }
        public List<string> UpDateHandlers = new List<string>();
        FpsMonitor fpsM;
        private BaseScene scene;
        SpriteFont textFont;
        public InputControl input;
        MainFormModel editerFormModel = null;
        string luaName = "";
        bool _isEditerMode = false;

        //normal mode
        public MainGame()
        {
            graphics = new GraphicsDeviceManager(this)
            {
                PreferredBackBufferHeight = GraphicConstant.WINDOW_HEIGHT,
                PreferredBackBufferWidth = GraphicConstant.WINDOW_WIDTH,
                IsFullScreen = false
            };
            Content.RootDirectory = "Content";
        }

        public MainGame(string scenePath)
        {
            this.luaName = scenePath;
            graphics = new GraphicsDeviceManager(this)
            {
                PreferredBackBufferHeight = GraphicConstant.WINDOW_HEIGHT,
                PreferredBackBufferWidth = GraphicConstant.WINDOW_WIDTH,
                IsFullScreen = false
            };
            Content.RootDirectory = "Content";
        }

        //editer mode
        public MainGame(MainForm form)
        {
            editerFormModel = form.PresentationModel;
            _isEditerMode = true;
            editerFormModel.LoadFileEvent += this.LoadScene;
            Content.RootDirectory = "Content";
            graphics = new GraphicsDeviceManager(this)
            {
                PreferredBackBufferHeight = GraphicConstant.WINDOW_HEIGHT,
                PreferredBackBufferWidth = GraphicConstant.WINDOW_WIDTH,
                IsFullScreen = false
            };

            graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
            System.Windows.Forms.Form xnaWindow = (System.Windows.Forms.Form)System.Windows.Forms.Control.FromHandle((this.Window.Handle));
            xnaWindow.GotFocus += new EventHandler(delegate(object sender, EventArgs e)
            {
                ((System.Windows.Forms.Form)sender).Visible = false;
                form.TopMost = false;
            });

        }

        private void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
        {
            e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle = this.editerFormModel.Panel.Handle;
        }

        static public GraphicsDevice GetGraphicsDevice()
        {
            return graphics.GraphicsDevice;
        }

        protected override void Initialize()
        {
            base.Initialize();

            IsMouseVisible = true;
            if (_isEditerMode)
                Mouse.WindowHandle = this.editerFormModel.Panel.Handle;
            else
                Mouse.WindowHandle = this.Window.Handle;
        }

        protected override void LoadContent()
        {
            base.LoadContent();
            ContentFactory.Initialize(this);
            input = new InputControl();
            fpsM = new FpsMonitor();

            textFont = Content.Load<SpriteFont>("images/SpriteFont1");
            SpriteBatch = new SpriteBatch(GraphicsDevice);

            LoadScene(luaName);

        }

        public void LoadScene(string _luaName)
        {
            if (scene != null)
                scene.Dispose();
            LuaSceneBuilder sceneModeler;
            if (_luaName == "")
                sceneModeler = new LuaSceneBuilder();
            else
                sceneModeler = new LuaSceneBuilder(_luaName);

            if (_isEditerMode)
            {
                scene = new LuaEditerScene(this, this.editerFormModel);
                this.editerFormModel.TargetScene = (LuaEditerScene)scene;
                this.editerFormModel.SceneModler = sceneModeler;
                this.editerFormModel.Update();
            }
            else
            {
                scene = new ConcreteScene(this);
            }

            scene.Build(sceneModeler, sceneModeler.SceneDefine);
            scene.SortChildren();
        }

        protected override void UnloadContent()
        {
            scene.Dispose();
            if (SpriteBatch != null)
                try
                {
                    SpriteBatch.Dispose();
                }
                catch (Exception)
                {
                }
        }

        public void AddUpDateHandler(string handler)
        {
            UpDateHandlers.Add(handler);
        }

        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            scene.OnUpdate(gameTime);
            fpsM.Update(gameTime);
            input.OnUpdate(gameTime);
            base.Update(gameTime);
        }



        protected override void Draw(GameTime gameTime)
        {

            GraphicsDevice.Clear(Color.Aqua);

            //SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            scene.OnDraw(gameTime, SpriteBatch);
            //SpriteBatch.End();

            SpriteBatch.Begin();
            string output = scene.Name + "\nFPS:" + fpsM.Value.ToString();
            output += "\n" + Mouse.GetState().ToString();
            SpriteBatch.DrawString(textFont, output, new Vector2(5, 5), Color.LightGreen);
            SpriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
